#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <gmp.h>
#include <pthread.h>

#define pontos  100000

//Declaração de variáveis globais
mpf_t  pi, aux3, aux4;

int pCirc[10];    // Quantidade de pontos no circulo para cada tread
int total;      //Total de pontos no circulo

void *montecarlo(void *aux){
        //Declaração de variáveis locais
        long long  i;
        int num = *((int *)aux);

    mpf_t x, y, z, aux1, aux2;
        mpf_init2(x,40000000);
        mpf_init2(y,40000000);
        mpf_init2(z,40000000);
        mpf_init2(aux1,40000000);
        mpf_init2(aux2,40000000);
    gmp_randstate_t state;

        mpf_set_d(x,0);
        mpf_set_d(y,0);
        mpf_set_d(z,0);
        mpf_set_d(aux1,0);
        mpf_set_d(aux2,0);

        gmp_randinit_default(state);
        gmp_randseed_ui(state,time(NULL));


        for(i = 0;i < pontos;i++){
                mpf_urandomb(x,state,100);   //X e Y recebem numeros randomicos
                mpf_urandomb(y,state,100);

                mpf_mul(aux1,x,x);
                mpf_mul(aux2,y,y);
                mpf_add(z,aux1,aux2);      //z = (x*x)+(y*y)


                if(mpf_cmp_d(z, 1) <= 0){
                        pCirc[num]++;       //Numero de pontos no Circulo
                }

        }

        mpf_clear(aux1);
        mpf_clear(aux2);
        mpf_clear(x);
        mpf_clear(y);
        mpf_clear(z);

    pthread_exit(NULL);
}

int main(void){
        //Declaração de variáveis locais
        int i;
    clock_t start,end;

        mpf_init2(aux3,40000000);
        mpf_init2(aux4,40000000);
        mpf_init2(pi,40000000);

        mpf_set_d(aux3,0);
        mpf_set_d(aux4,0);

        //Declaração de treads
        pthread_t t[10];

    start=clock();
        for (i = 0; i < 10 ; i++){
                pthread_create (&t[i], NULL, montecarlo, &i);    //Cria as 10 threads que serão usadas
        }

        for (i = 0; i < 10; i++){
                pthread_join (t[i], NULL);   //Junta as threads
        }

        for (i = 0; i < 10 ; i++){
                total += pCirc[i];     //Calcula o total de pontos no circulo
        }

        mpf_set_ui(aux3,pontos);
        mpf_mul_ui(aux3,aux3,10);
        mpf_set_ui(aux4,total);
        mpf_div(aux4,aux4,aux3);
        mpf_mul_ui(pi,aux4,4);   //pi=(Numero total de pontos no circulo/Numero total de pontos)*4

    end=clock();
        gmp_printf("Pi = %.100Ff\n",pi);
        printf("\n--Tempo %ld--\n",(end - start)/CLOCKS_PER_SEC);

        mpf_clear(aux3);
        mpf_clear(aux4);

        pthread_exit(NULL);

return 0;

}
